package org.eremite.corm.party;

import sun.reflect.generics.reflectiveObjects.NotImplementedException;

import java.util.Date;
import java.util.Map;
import java.util.HashMap;

import org.eremite.corm.party.relationship.PartyRole;
import org.eremite.corm.party.relationship.PartyRoleType;
import org.eremite.corm.party.relationship.Responsibility;
import org.eremite.corm.party.relationship.Capability;
import org.eremite.corm.party.address.*;

public abstract class Monadyne {

    public static Organization getInstance() {

        // TODO: fix this later, to rep. future date (for all DATES)
        Date validFromDate = new Date();

        Organization result = new Organization();
        OrganizationName orgName = new OrganizationName();
        orgName.setName("Monadyne");
        orgName.setValidFrom(validFromDate);

        result.setOrgName(orgName);

        // Define People
        Person Nosh, Vakes, Bain, Cholaxu;
        Nosh = new Person(personName("Nosh", "Toran", "Toran", "Mr.", new Date()));
        Vakes = new Person(personName("Vakes", "Braimen", "Mr. Vakes", "Mr.", new Date()));
        Bain = new Person(personName("Bain", "Cialla", "Cialla", "Ms.", new Date()));
        Cholaxu = new Person(personName("Cholaxu", "Lorn", "Lorn", "Mr.", new Date()));

        Nosh.setDescription("Heterarch and Mechatronician in Monadyne Corp");
        Vakes.setDescription("Mentat of Monadyne Corp");
        Bain.setDescription("Heterarch and Gunboat in Monadyne Corp");
        Cholaxu.setDescription("Founder and Heterarch of Monadyne Corp");

        Nosh.setGender(0);
        Vakes.setGender(0);
        Bain.setGender(1);
        Cholaxu.setGender(0);

        // Adding PartyRoles
        Map<String, Responsibility> duties = new HashMap<String, Responsibility>();
        duties.put("Praising", new Responsibility("Praising", "May, if so inclined, sing praises of their Heterarch providers"));
        duties.put("Obedience", new Responsibility("Obedience", "Carry out missions as assigned by Heterarchs"));
        duties.put("Descision Making", new Responsibility("Descision Making","Take part in the determination of corporate actions"));
        duties.put("Leadership", new Responsibility("Leadership","Example is good, leashes are acceptable."));
        duties.put("Research", new Responsibility("Research", "Research blueprints to improve quality and efficiency"));
        duties.put("Agent Research", new Responsibility("Agent Research", "Conduct missions with corporate agents"));
        duties.put("Copying", new Responsibility("Copying", "Arranging for copies to be made of blueprints"));
        duties.put("Refining", new Responsibility("Refining", "Refine ore for production or sale"));
        duties.put("Manufacturing", new Responsibility("Manufacturing", "Use refined ore for the production of goods"));
        duties.put("Specialization", new Responsibility("Specialization","Should specialize in either Manufacturing or Refining"));
        duties.put("Sale", new Responsibility("Sale", "Post corporate goods for sale on the market"));
        duties.put("Purchasing", new Responsibility("Purchasing", "Buy products on behalf of the corporation"));
        duties.put("Transportation", new Responsibility("Transportion","Should be capable of transporting goods for sale"));


        PartyRoleType type1, type2, type3, type4, type5, type6;
        type1 = partyRoleType(
                "Myrmidon",
                pkg(duties.get("Obedience")),
                pkg(duties.get("Praising")),
                pkg(new Binding()));

        type2 = partyRoleType(
                "Heterarch",
                pkg(duties.get("Descision Making")),
                pkg(duties.get("Leadership")),
                pkg(new Binding()));

        type3 = partyRoleType(
                "Corporation",
                pkg(new Responsibility("","")),
                pkg(new Responsibility("","")),
                pkg(new Binding()));

        type4 = partyRoleType(
                "Mentat",
                pkg(duties.get("Research"),
                        duties.get("Agent Research"),
                        duties.get("Copying")),
                pkg(duties.get("Praising")),
                pkg(new Binding()));

        type5 = partyRoleType(
                "Mechatronician",
                pkg(duties.get("Refining"),
                        duties.get("Manufacturing")),
                pkg(duties.get("Praising"),
                        duties.get("Specialization")),
                pkg(new Binding()));

        type6 = partyRoleType(
                "Mercer",
                pkg(duties.get("Sale"),
                        duties.get("Purchasing")),
                 pkg(duties.get("Praising"),
                        duties.get("Transportation")),
                pkg(new Binding()));

        Nosh.addPartyRole(partyRoles(Nosh, type2, type5));
        Vakes.addPartyRole(partyRoles(Vakes, type4, type6, type1));
        Bain.addPartyRole(partyRoles(Bain, type2, type6));
        Cholaxu.addPartyRole(partyRoles(Cholaxu, type2));
        result.addPartyRole(partyRoles(result, type3));

        // Capabilities
        // TODO: Correct capability structure
        Capability purchase, sell, refine, praise, research;
                purchase = new Capability();
                sell = new Capability();
                refine = new Capability();
                praise = new Capability();
                research = new Capability();

        purchase.setName("Purchase");
        purchase.setDescription("Make purchases using corporate funds");

        sell.setName("Sales");
        sell.setDescription("Sell corporate products");

        refine.setName("Refine");
        refine.setDescription("Refine ore collected by Myrmydons");

        praise.setName("Praise");
        praise.setDescription("Praise Heterach providers");

        Nosh.addCapability(purchase, sell, refine);
        Vakes.addCapability(purchase, sell, research);
        Bain.addCapability(purchase, sell);
        Cholaxu.addCapability(purchase, sell);

        // Preferences
        BindingType shipMake = new BindingType("Ship Make");
        BindingValue gallente, matari, caldari, amaaran;
        gallente = new BindingValue("Gallente", "Ships made by the Gallente Federation");
        matari = new BindingValue("Matari", "Ships built by the Minmatar Republic");
        caldari = new BindingValue("Caldari", "Ships of the Caldari State");
        amaaran = new BindingValue("Amarran", "Ships built by the Amaar Empire");

        shipMake.setDescription("Preferred Make of various ship classes");
        shipMake.addOption(gallente, matari, caldari, amaaran);

        Binding makePref1, makePref2, makePref3, makePref4;
                makePref1 = new Binding("Gallente Prefernce", shipMake, gallente);
                makePref2 = new Binding("Minmatar Binding", shipMake, matari);
                makePref3 = new Binding("Caldari Binding", shipMake, caldari);
                makePref4 = new Binding("Amaar Binding", shipMake, matari);

        makePref1.setSalience(90);
        makePref2.setSalience(10);
        makePref3.setSalience(3);
        makePref4.setSalience(1);

        BindingType shipClass = new BindingType("Ship Class");
        BindingValue frigate, destroyer, cruiser, battleCruiser, battleShip, miningBarge, industrial, shuttle;
                frigate = new BindingValue("Frigates", "Small ships, capable of quick flight and high agility");
                destroyer = new BindingValue("Destroyers", "High-powered frigates");
                cruiser = new BindingValue("Cruiser", "Anti-frigate gunboats. Midway between a frigate and a cruiser.");
                battleCruiser = new BindingValue("Battle Cruisers", "Combat ships between cruisers and battleships.");
                battleShip = new BindingValue("Battle Ships", "The foundations of any respectable fighting force.");
                miningBarge = new BindingValue("Mining Barge", "Lumbering hulks, created for ore accumulation.");
                industrial = new BindingValue("Industrial Ships","Transportation of vast stores of cargo.");
                shuttle = new BindingValue("Shuttle", "Barely more than a capsule with engines");

        shipClass.setDescription("Preferred class of ship");
        shipClass.addOption(frigate, destroyer, cruiser, battleCruiser, battleShip, miningBarge, industrial, shuttle);

        Binding classPref1, classPref2, classPref3, classPref4, classPref5, classPref6, classPref7, classPref8;
                classPref1 = new Binding("Frigate Binding", shipClass, frigate);
                classPref2 = new Binding("Destroyer Binding", shipClass, destroyer);
                classPref3 = new Binding("Cruiser Binding", shipClass, cruiser);
                classPref4 = new Binding("Battle Cruiser Binding", shipClass, battleCruiser);
                classPref5 = new Binding("Battle Ship Binding", shipClass, battleShip);
                classPref6 = new Binding("Mining Barge Binding", shipClass, miningBarge);
                classPref7 = new Binding("Industrial Binding", shipClass, industrial);
                classPref8 = new Binding("Shuttle", shipClass, shuttle);


        Nosh.addPreference(makePref1, classPref6, classPref7);
        Vakes.addPreference(makePref1, classPref8, classPref1);
        Bain.addPreference(makePref1, classPref4, classPref3, classPref2);
        Cholaxu.addPreference(makePref1, classPref5);

        // Add addresses
        new AssociatedAddress(Nosh, newAddress("home", "home addres", new Date()), "home", "home address");
        new AssociatedAddress(Vakes, newAddress("home", "home addres", new Date()), "home", "home address");
        new AssociatedAddress(Bain, newAddress("home", "home addres", new Date()), "home", "home address");
        new AssociatedAddress(Cholaxu, newAddress("home", "home addres", new Date()), "home", "home address");

        new AssociatedAddress(Nosh, newEmail("ToranNosh@eve-mail.com"), "email", "ToranNosh@eve-mail.com");
        new AssociatedAddress(Vakes, newEmail("BraimenVakes@eve-mail.com"), "email", "BraimenVakes@eve-mail.com");
        new AssociatedAddress(Bain, newEmail("CiallaBain@eve-mail.com"), "email", "CiallaBain@eve-mail.com");
        new AssociatedAddress(Cholaxu, newEmail("LornCholaxu@eve-mail.com"), "email","LornCholaxu@eve-mail.com");

        GeographicAddress geoAdd1 = new GeographicAddress();

        // TODO: Correct Station Address
        new AssociatedAddress(Nosh, geoAdd1, "Station","");
        new AssociatedAddress(Vakes, geoAdd1, "Station","");
        new AssociatedAddress(Bain, geoAdd1, "Station","");
        new AssociatedAddress(Cholaxu, geoAdd1, "Station","");
        new AssociatedAddress(result, geoAdd1, "Station","");

        WebPageAddress web = new WebPageAddress("http://monadyne.eremite.org/");
        
        new AssociatedAddress(Nosh, web, "Monadyne Corporate Site","Address of the Monadyne Corp. Web site");
        new AssociatedAddress(Vakes, web, "Monadyne Corporate Site","Address of the Monadyne Corp. Web site");
        new AssociatedAddress(Bain, web, "Monadyne Corporate Site","Address of the Monadyne Corp. Web site");
        new AssociatedAddress(Cholaxu, web, "Monadyne Corporate Site","Address of the Monadyne Corp. Web site");
        new AssociatedAddress(result, web, "Monadyne Corporate Site","Address of the Monadyne Corp. Web site");

        //TODO: Add further reg IDs
        Cholaxu.addRegisteredIdentifier(newRegId("Gallente Military", "Gallente Military Academy", "a423hjdfg"));

        Vakes.addPseudonym(newPseudonym("Masker Van Bie"));

        throw new NotImplementedException();

    }

    private static PersonName personName(
            String f,
            String g,
            String p,
            String pre,
            Date d) {

        PersonName result = new PersonName();
        result.setFamilyName(f);
        result.setGivenName(g);
        result.setPreferredName(p);
        result.setPrefix(pre);
        result.setValidFrom(d);

        return result;
    }

    private static PartyRoleType partyRoleType(
            String n,
            Responsibility[] mandatories,
            Responsibility[] optional,
            Binding[] props) {

        PartyRoleType result = new PartyRoleType();
        result.setName(n);
        result.addMandatoryResponsibility(mandatories);
        result.addOptionalResponsibility(optional);
        result.addProperty(props);

        return result;
    }

    private static Responsibility[] pkg(Responsibility ... r) { return r; }
    private static Binding[] pkg(Binding ... p) { return p; }

    private static PartyRole partyRoles(Party p, PartyRoleType ... types) {

        PartyRole pRoles = new PartyRole();
        p = new Party();

        for ( PartyRoleType type1 : types ) {
            pRoles = new PartyRole(type1, p);
        }

        return pRoles;

    }

    private static Address newAddress(String name, String desc, Date d) {

       Address addy = new Address();

       addy.setName(name);
       addy.setDescription(desc);
       addy.setValidFrom(d);

       return addy;

    }

    private static EmailAddress newEmail(String address) {

        EmailAddress email = new EmailAddress();

        email.setEmailAddress(address);

        return email;

    }

    private static RegisteredIdentifier newRegId(String type, String authority, String contents) {

        RegisteredIdentifier reg = new RegisteredIdentifier();

        reg.setType(type);
        reg.setRegistrationAuthority(authority);
        reg.setContents(contents);

        return reg;
    }

    private static PersonName newPseudonym(String name) {

        PersonName pseudo = new PersonName(name);
        return pseudo;

    }
}
